import java.io.File;
import java.io.FileOutputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.sun.org.apache.xml.internal.serialize.OutputFormat;
import com.sun.org.apache.xml.internal.serialize.XMLSerializer;

import iPod.*;

public class Application {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		if (args.length != 3)
		{
			System.out.println("args: <ipodDB Dir> <iTunesDB> <outputItunesDB>");
			return;
		}
		
		IPod pod = new IPod();
		pod.load(args[0]);
		
		File inputFile = new File(args[1]);
		File outputFile = new File(args[2]);
		
		try
		{
			// Load the XML document
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			dbf.setValidating(false);
			Document doc = db.parse(inputFile);
			doc.getDocumentElement().normalize();

			// Perform intermediate processing
			String nodeName = doc.getDocumentElement().getNodeName();
			Node root = doc.getDocumentElement().getFirstChild();
			while(root.getNodeType() != Node.ELEMENT_NODE)
				root = root.getNextSibling();			
			NodeList keys = ((Element)root).getElementsByTagName("key");
			// Find the key "Tracks"
			Node tracks = null;
			for (int index = 0; index < keys.getLength(); ++index)
			{
				tracks = keys.item(index);
				if (tracks.getTextContent().equalsIgnoreCase("Tracks"))
				{
					tracks = tracks.getNextSibling();
					while(tracks.getNodeType() != Node.ELEMENT_NODE)
						tracks = tracks.getNextSibling();								
					break;
				}
			}
			if (!tracks.getNodeName().equalsIgnoreCase("dict"))
				return;
			
			int trackCount = 0;
			Node track = tracks.getFirstChild();
			while(track.getNodeType() != Node.ELEMENT_NODE)
				track = track.getNextSibling();				
			while (track != null)
			{
				if (track.getNodeName().equalsIgnoreCase("dict"))
				{				
					String artist = "";
					String album = "";
					String title = "";
					int filesize = 0;
					int origRating = 0;
					Node ratingNode = null;
					Node expectedRating = null;
					
					keys = ((Element)track).getElementsByTagName("key");
					for (int index = 0; index < keys.getLength(); ++index)
					{
						Node key = keys.item(index);
						String keyName = key.getTextContent();
						if (keyName.equalsIgnoreCase("Track ID"))
						{
							Node value = key.getNextSibling();
							while(value.getNodeType() != Node.ELEMENT_NODE)
								value = value.getNextSibling();	
							String trackID = value.getTextContent();
							System.out.print("CurTrack("+trackID+") - ");
						}
						else if (keyName.equalsIgnoreCase("Name"))
						{
							Node value = key.getNextSibling();
							while(value.getNodeType() != Node.ELEMENT_NODE)
								value = value.getNextSibling();	
							title = value.getTextContent();
						}
						else if (keyName.equalsIgnoreCase("Artist"))
						{
							Node value = key.getNextSibling();
							while(value.getNodeType() != Node.ELEMENT_NODE)
								value = value.getNextSibling();	
							artist = value.getTextContent();
						}
						else if (keyName.equalsIgnoreCase("Album"))
						{
							Node value = key.getNextSibling();
							while(value.getNodeType() != Node.ELEMENT_NODE)
								value = value.getNextSibling();	
							album = value.getTextContent();
						}
						else if (keyName.equalsIgnoreCase("Size"))
						{
							Node value = key.getNextSibling();
							while(value.getNodeType() != Node.ELEMENT_NODE)
								value = value.getNextSibling();	
							filesize = Integer.parseInt(value.getTextContent());
						}
						else if (keyName.equalsIgnoreCase("Rating"))
						{
							Node value = key.getNextSibling();
							while(value.getNodeType() != Node.ELEMENT_NODE)
								value = value.getNextSibling();	
							
							origRating = Integer.parseInt(value.getTextContent());	
							ratingNode = value;
							expectedRating = ratingNode;
						}
						else
						{
							if (keyName.equalsIgnoreCase("Album Rating") && expectedRating == null)
							{
								expectedRating = key;
							}
							else if (keyName.equalsIgnoreCase("Album Rating Computed") && expectedRating == null)
							{
								expectedRating = key;
							}
							else if (keyName.equalsIgnoreCase("Sort Name") && expectedRating == null)
							{
								expectedRating = key;
							}
							else if (keyName.equalsIgnoreCase("Sort Artist") && expectedRating == null)
							{
								expectedRating = key;
							}
							else if (keyName.equalsIgnoreCase("Sort Album") && expectedRating == null)
							{
								expectedRating = key;
							}
							else if (keyName.equalsIgnoreCase("Persistent ID") && expectedRating == null)
							{
								expectedRating = key;
							}							
						}
					}
					
					// Check if the rating matches that in the itunesDB
					String trackKey = pod.GenerateTrackKey(artist, album, title, filesize);
					TrackItem item = pod.GetTrackRecord(trackKey);
					trackCount++;
					if (item != null && (origRating == 0 && item.getRating() != 0))
					{
						System.out.println(trackCount+ " - Updating Rating (" + origRating+"->"+item.getRating()+"): " + trackKey);
						
						if (ratingNode == null)
						{
							if (expectedRating == null)
								System.out.println("Oh shit, no idea where to put this...");							
							
							Element nkey = null;
							while(!expectedRating.getTextContent().equalsIgnoreCase("Album Rating"))
							{
								if (expectedRating.getTextContent().equalsIgnoreCase("Album Rating Computed"))
								{
									nkey = doc.createElement("key");
									nkey.setTextContent("Album Rating");
									ratingNode = doc.createElement("integer");
									ratingNode.setTextContent("0");
									
									track.insertBefore(ratingNode, expectedRating);
									track.insertBefore(nkey, ratingNode);
								}
								else
								{
									nkey = doc.createElement("key");
									nkey.setTextContent("Album Rating Computed");
									ratingNode = doc.createElement("true");
									
									track.insertBefore(ratingNode, expectedRating);
									track.insertBefore(nkey, ratingNode);
								}
								
								expectedRating = nkey;
							}
							
							nkey = doc.createElement("key");
							nkey.setTextContent("Rating");
							ratingNode = doc.createElement("integer");
							
							track.insertBefore(ratingNode, expectedRating);
							track.insertBefore(nkey, ratingNode);						
						}
						
						ratingNode.setTextContent(Integer.toString(item.getRating()));
					}					
					else if (item == null)
					{
						System.out.println(trackCount+ " - Couldn't find: "+trackKey);
					}
					else
					{
						System.out.println(trackCount+ " - NOT updating Rating (" + origRating+"->"+item.getRating()+"): " + trackKey);
					}
				}
					
				track = track.getNextSibling();
			}
			
			// Output the results		
			FileOutputStream fos = new FileOutputStream(outputFile);
			OutputFormat of = new OutputFormat("XML","UTF-8",true);
			of.setIndent(1);
			of.setIndenting(true);
			of.setDoctype(null, "users.dtd");
			XMLSerializer serializer = new XMLSerializer(fos,of);
			serializer.asDOMSerializer();
			serializer.serialize( doc.getDocumentElement() );
			fos.close();
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		
	}

}
